home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / SmallTalk / mstsysdep.c < prev    next >
C/C++ Source or Header  |  1995-08-25  |  8KB  |  339 lines

  1. /***********************************************************************
  2.  *
  3.  *    System specific implementation module.
  4.  *
  5.  *    This module contains implementations of various operating system
  6.  *    specific routines.  This module should encapsulate most of these OS
  7.  *    specific calls so that the rest of the code is portable.
  8.  *
  9.  ***********************************************************************/
  10.  
  11. /***********************************************************************
  12.  *
  13.  * Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  14.  * Written by Steve Byrne.
  15.  *
  16.  * This file is part of GNU Smalltalk.
  17.  *
  18.  * GNU Smalltalk is free software; you can redistribute it and/or modify it
  19.  * under the terms of the GNU General Public License as published by the Free
  20.  * Software Foundation; either version 1, or (at your option) any later 
  21.  * version.
  22.  * 
  23.  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  24.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  25.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  26.  * more details.
  27.  * 
  28.  * You should have received a copy of the GNU General Public License along with
  29.  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  30.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  31.  *
  32.  ***********************************************************************/
  33.  
  34.  
  35. /*
  36.  *    Change Log
  37.  * ============================================================================
  38.  * Author      Date       Change 
  39.  * sbb         28 Nov 91      Added getCurDirName() for allowing compiler to record
  40.  *              the full file name that is used.
  41.  *
  42.  * sbb          5 Jan 91      Added getMilliTime().
  43.  *
  44.  * sbyrne    17 May 90      Added enableInterrupts and disableInterrupts.  System
  45.  *              V.3 code signal support from Doug McCallum (thanks,
  46.  *              Doug!).
  47.  *
  48.  * sbyrne    16 May 90      Created.
  49.  *
  50.  */
  51.  
  52. #include "mst.h"
  53. #include "mstsysdep.h"
  54. #include <signal.h>
  55. #include <sys/types.h>
  56. #include <sys/time.h>
  57. #include <sys/param.h>
  58. #if defined(USG)
  59. #include <sys/times.h>
  60. #endif
  61.  
  62. #ifdef SYSV_3_SIGNALS
  63. static unsigned long __cursigmask; /* keep track of signal mask status */
  64. #endif
  65.  
  66. /*
  67.  *    IntState disableInterrupts()
  68.  *
  69.  * Description
  70.  *
  71.  *    Saves and returns the current state of the software interrupt system.
  72.  *    Disables all interrupts.
  73.  *
  74.  * Outputs
  75.  *
  76.  *    The old state of the interrupt system (presumably for saving for a
  77.  *    later call to enableInterrupts).
  78.  */
  79. IntState disableInterrupts()
  80. {
  81. #ifdef BSD_SIGNALS
  82.   return (sigsetmask(-1));
  83. #endif
  84. #ifdef SYSV_3_SIGNALS
  85.   unsigned long oldmask = __cursigmask;
  86.   register int i;
  87.  
  88.   __cursigmask = -1;
  89.   for (i=1; i <= 32; i++) {
  90.     sighold(i);        /* want it blocked - ok if it already is */
  91.   }
  92.   return oldmask;
  93. #endif
  94. }
  95.  
  96.  
  97. /*
  98.  *    void enableInterrupts(mask)
  99.  *
  100.  * Description
  101.  *
  102.  *    Restores the state of the interrupt system to that which it had when
  103.  *    "mask" was created. 
  104.  *
  105.  * Inputs
  106.  *
  107.  *    mask  : An interrupt state...should have been returned at some point
  108.  *        from a call to disableInterrupts.
  109.  *
  110.  */
  111. void enableInterrupts(mask)
  112. IntState mask;
  113. {
  114. #ifdef BSD_SIGNALS
  115.   sigsetmask(mask);
  116. #endif
  117. #ifdef SYSV_3_SIGNALS
  118.   unsigned long oldmask = __cursigmask;
  119.   register int i;
  120.  
  121.   __cursigmask = mask;
  122.   for (i=1; mask != 0; i++, mask >>= 1) { 
  123.     if (oldmask & (0x1 << (i-1))) {
  124.       sigrelse(i);    /* want it unblocked and it is blocked */
  125.     }
  126.   }
  127. #endif
  128. }
  129.  
  130. /*
  131.  *    unsigned long getMilliTime()
  132.  *
  133.  * Description
  134.  *
  135.  *    Returns the local time in milliseconds
  136.  *
  137.  */
  138. unsigned long getMilliTime()
  139. {
  140. #if !defined(USG)
  141.   struct timeval t;
  142.  
  143.   gettimeofday(&t, nil);
  144.   return (t.tv_sec * 1000 + t.tv_usec / 1000);
  145. #else
  146.   time_t t;
  147.   struct tms dummy;
  148.  
  149.   t = times(&dummy);
  150.   return (t * 1000 / gethz());
  151. #endif
  152. }
  153.  
  154.  
  155. /*
  156.  *    unsigned long getTime()
  157.  *
  158.  * Description
  159.  *
  160.  *    Returns the time in seconds since midnight Jan 1, 1970 (standard UNIX
  161.  *    type time).  There should be a better (more generic) way to get this
  162.  *    information, but there doesn't seem to be.  Once things are POSIX
  163.  *    compliant, life will be much better :-)
  164.  *
  165.  * Outputs
  166.  *
  167.  *    As described above.
  168.  */
  169. unsigned long getTime()
  170. {
  171. #if !defined(USG)
  172.   struct timeval t;
  173.  
  174.   gettimeofday(&t, nil);
  175.   return (t.tv_sec);
  176. #else
  177.   time_t    t;
  178.  
  179.   time(&t);
  180.   return ((unsigned long) t);
  181. #endif
  182. }
  183.  
  184. /*
  185.  *    void signalAfter(deltaMilli, func)
  186.  *
  187.  * Description
  188.  *
  189.  *    Set up func as a signal handler to be called after deltaMilli
  190.  *    milliseconds.
  191.  *
  192.  * Inputs
  193.  *
  194.  *    deltaMilli: 
  195.  *        Time in milliseconds before the function is invoked.  Rounded
  196.  *        up to nearest second for machines without higher precision
  197.  *        timers.
  198.  *    func  : Signal handling function invoked when interval expires
  199.  *
  200.  * Outputs
  201.  *
  202.  *    None.
  203.  */
  204. void signalAfter(deltaMilli, func)
  205. int    deltaMilli;
  206. signalType (*func)();
  207. {
  208. /* Please feel free to make this more accurate for your operating system
  209.  * and send me the changes.
  210.  */
  211.  
  212. #ifdef ITIMER_REAL
  213.   struct itimerval value;
  214.  
  215.     value.it_interval.tv_sec = value.it_interval.tv_usec = 0;
  216.   if (deltaMilli <= 0) {
  217.     /* If we have a negative delta time, we should signal the interrupt NOW.
  218.      * We could do this by just invoking FUNC by hand, but FUNC may expect to
  219.      * be called in the contect of an interrupt handler, and it would be
  220.      * tricky to fake that.  We therefore just make the interrupt handler
  221.      * be called as soon as possible.
  222.      */
  223.     value.it_value.tv_sec = 0;
  224.     value.it_value.tv_usec = 1;    /* smallest possible  */
  225.   } else {
  226.     value.it_value.tv_sec = deltaMilli/1000;
  227.     value.it_value.tv_usec = (deltaMilli%1000) * 1000;
  228.   }
  229.  
  230.   signal(SIGALRM, func);
  231.   setitimer(ITIMER_REAL, &value, (struct itimerval *)0);
  232. #else 
  233.   int        timeSecs;
  234.  
  235.   if (deltaMilli < 0) {
  236.     timeSecs = 1;
  237.   } else {
  238.     timeSecs = (deltaMilli + 999)/ 1000; /* round up to nearest second */
  239.   }
  240.   signal(SIGALRM, func);
  241.  
  242.   alarm(timeSecs);
  243. #endif  
  244. }
  245.  
  246.  
  247. /*
  248.  *    char *getCurDirName()
  249.  *
  250.  * Description
  251.  *
  252.  *    Returns the path name for the current directory, without trailing
  253.  *    delimiter (?).
  254.  *
  255.  * Outputs
  256.  *
  257.  *    Pointer to allocated string for current path name.  Caller has
  258.  *    responsibility for freeing the returned value when through.
  259.  */
  260. char *getCurDirName()
  261. {
  262.   char        name[MAXPATHLEN];
  263.   extern char    *strdup();
  264.  
  265.   getwd(name);
  266.   return (strdup(name));
  267. }
  268.  
  269.  
  270. /*
  271.  *    char *getFullFileName(fileName)
  272.  *
  273.  * Description
  274.  *
  275.  *    Returns the full path name for a given file.
  276.  *
  277.  * Inputs
  278.  *
  279.  *    fileName: 
  280.  *        Pointer to file name, can be relative or absolute
  281.  *
  282.  * Outputs
  283.  *
  284.  *    Full path name string.  Caller has the responsibility for freeing the
  285.  *    returned string.
  286.  */
  287. char *getFullFileName(fileName)
  288. char    *fileName;
  289. {
  290.   char        *fullFileName;
  291.   static char    *fullPath = NULL;
  292.   extern char    *strdup();
  293.  
  294.   if (fileName[0] == '/') {    /* absolute, so don't need to change */
  295.     return (strdup(fileName));
  296.   }
  297.  
  298.   if (fullPath == NULL) {
  299.     /* Only need to do this once, then cache the result */
  300.     fullPath = getCurDirName();
  301.   }
  302.  
  303.   /*
  304.    * ### canonicalize filename and full path here in the future (remove any
  305.    * extraneous .. or . directories, etc.)
  306.    */
  307.  
  308.   fullFileName = (char *)malloc(strlen(fullPath) + strlen(fileName)
  309.                 + 1 /* slash */
  310.                 + 1 /* trailing nul */);
  311.   sprintf(fullFileName, "%s/%s", fullPath, fileName);
  312.   return (fullFileName);
  313. }
  314.  
  315.  
  316. #ifdef WANT_DPRINTF
  317.  
  318. #include <varargs.h>
  319.  
  320. dprintf(va_alist)
  321. va_dcl
  322. {
  323.   va_list    args;
  324.   char        *fmt;
  325.   static    FILE    *debFile = NULL;
  326.  
  327.   if (debFile == NULL) {
  328.     debFile = fopen("mst.deb", "w");
  329.   }
  330.   
  331.   va_start(args);
  332.   fmt = va_arg(args, char *);
  333.   (void) vfprintf(debFile, fmt, args);
  334.   fflush(debFile);
  335.   va_end(args);
  336. }
  337.  
  338. #endif
  339.